【小ネタ】AWS CloundFormationのYAMLテンプレート内のJSONで変数を使う
こんにちはCX事業本部のさかじです。
初めてAWS CloudFormationを使って自作のテンプレートを作りました。変数を使う際にYAMLの中にJSONが入っていると書式を注意しなければならないことがありハマってしまったのでまとめました。
はじめに
よく見る以下のサンプルポリシーを改善して「決められたアカウントIDからのデバイスのみpublishを許可するポリシー」を作成したいと思います。
変更前のポリシー
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iot:Publish", "iot:Subscribe", "iot:Connect", "iot:Receive" ], "Resource": "*" } ] }
変更後のポリシー
開発者ガイド>パブリッシュ/サブスクライブポリシーの例参考に作成
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iot:Connect" ], "Resource": [ "arn:aws:iot:ap-northeast-1:123456789012:client/testThing" ] }, { "Effect": "Allow", "Action": [ "iot:Publish" ], "Resource": [ "arn:aws:iot:ap-northeast-1:123456789012:topic/testThing/*" ] } ] }
CFnのテンプレート
AWS::IoT::Policyのドキュメントを確認しながらテンプレートを作ってみます
Syntax(YAML)
Type: AWS::IoT::Policy Properties: PolicyDocument: Json PolicyName: String
作ってみた
AWSTemplateFormatVersion: '2010-09-09' Description: Create IoT Publish policy. Resources: IoTShadowPolicy: Type: AWS::IoT::Policy Properties: PolicyDocument: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iot:Connect" ], "Resource": [ "arn:aws:iot:iot:ap-northeast-1:123456789012:client/*" ] }, { "Effect": "Allow", "Action": [ "iot:Publish" ], "Resource": [ "arn:aws:iot:ap-northeast-1:123456789012:topic/testThing/*" ] } ] } PolicyName: "IoTPubulishPolicyTest1"
問題点
このままですと別のAWSアカウントや別のリージョンへCFnのテンプレートを持っていても、適切な環境へ書き換えるためには毎回テンプレートを書き換える必要があります。
そこで変数を使い、リージョンやアカウントIDの変更にも対応できるようにします。
Fn::Subのドキュメントを確認して変数を使えるようにします。
- 参考 : マッピングなしの Fn::Sub
JSON
{ "Fn::Sub" : "arn:aws:iot:${AWS::Region}:${AWS::AccountId}:client/*" }
YAML
!Sub 'arn:aws:iot:${AWS::Region}:${AWS::AccountId}:client/*'
ここで疑問が出てきました。IoTのポリシーの書式(YAML)で書いてありますが、PolicyDocument
はJSON objectとされています。JSONで記入する必要がありますので以下のように変数を使えるようなテンプレートが出来上がります。
AWSTemplateFormatVersion: '2010-09-09' Description: Create IoT Device Shadow policy. Resources: IoTShadowPolicy: Type: AWS::IoT::Policy Properties: PolicyDocument: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iot:Connect" ], "Resource": [ "Fn::Sub" : "arn:aws:iot:${AWS::Region}:${AWS::AccountId}:client/*" ] }, { "Effect": "Allow", "Action": [ "iot:Publish" ], "Resource": [ "Fn::Sub" : "arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/testThing/*" ] } ] } PolicyName: "IoTPubulishPolicyTest2"
参考サイト
- 開発者ガイド>パブリッシュ/サブスクライブポリシーの例
- AWS::IoT::Policy
- AWS > ドキュメント > AWS CloudFormation > ユーザガイド > Fn::Sub
- プログラマーのための YAML 入門 (初級編)
- 【CloudFormation入門】5分と6行で始めるAWS CloudFormationテンプレートによるインフラ構築
最後に
YAMLの中にJSONが入っていてどうやって変数を入れるのか?と悩んでいたところ、単純な結果でしたが解決してよかったです。調子に乗ってもうちょっとCFnと仲良くなれるようになりたいと思います。